package com.un.ebs.workOrder.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.un.ebs.core.common.GroupListInfo;
import com.un.ebs.core.enums.SexEnum;
import com.un.ebs.core.enums.UserTypeEnum;
import com.un.ebs.core.exception.BusinessEntityNotFoundException;
import com.un.ebs.core.exception.BusinessException;
import com.un.ebs.core.form.FormBase;
import com.un.ebs.core.util.DateUtils;
import com.un.ebs.core.util.OSSUtil;
import com.un.ebs.core.util.SecurityUtils;
import com.un.ebs.core.util.StringUtils;
import com.un.ebs.customer.CustomerConfigureCode;
import com.un.ebs.customer.domain.Customer;
import com.un.ebs.customer.dto.CustomerTraceAddDto;
import com.un.ebs.customer.enums.RemindTypeEnum;
import com.un.ebs.customer.event.CustomerTraceEvent;
import com.un.ebs.customer.mapper.CustomerMapper;
import com.un.ebs.customer.service.CustomerService;
import com.un.ebs.customer.service.CustomerTraceService;
import com.un.ebs.customer.service.DefunctService;
import com.un.ebs.order.domain.*;
import com.un.ebs.order.dto.OrderItemUpdateQtyAndPriceDto;
import com.un.ebs.order.mapper.BzOrderMapper;
import com.un.ebs.order.mapper.OrderItemExtMapper;
import com.un.ebs.order.service.OrderService;
import com.un.ebs.product.enums.ProductPriceConfirmTypeEnum;
import com.un.ebs.product.enums.ProductUnitTypeEnum;
import com.un.ebs.sys.domain.Personnel;
import com.un.ebs.sys.domain.User;
import com.un.ebs.sys.mapper.UserMapper;
import com.un.ebs.sys.service.ConfigureService;
import com.un.ebs.sys.service.PersonnelService;
import com.un.ebs.sys.service.UserService;
import com.un.ebs.sys.service.WxService;
import com.un.ebs.workOrder.WorkOrderConfigureCode;
import com.un.ebs.workOrder.domain.WorkOrder;
import com.un.ebs.workOrder.domain.WorkOrderExt;
import com.un.ebs.workOrder.dto.*;
import com.un.ebs.workOrder.enums.RoleTypeEnum;
import com.un.ebs.workOrder.enums.WorkOrderStatusEnum;
import com.un.ebs.workOrder.mapper.WorkOrderExtMapper;
import com.un.ebs.workOrder.mapper.WorkOrderMapper;
import com.un.ebs.workOrder.service.WorkOrderService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liubo
 * @since 2019-11-18
 */
@Service
public class WorkOrderServiceImpl extends ServiceImpl<WorkOrderMapper, WorkOrder> implements WorkOrderService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private CustomerMapper customerMapper;

    @Resource
    private CustomerService customerService;

    @Resource
    private DefunctService defunctService;

    @Resource
    private OrderService orderService;

    @Resource
    private WorkOrderExtMapper workOrderExtMapper;

    @Resource
    private WorkOrderMapper workOrderMapper;

    @Resource
    private PersonnelService personnelService;

    @Resource
    private ConfigureService configureService;

    @Resource
    private WxService wxService;

    private final String prefix = "work_order";
    private final String suffix_create = "create";
    private final String suffix_accept = "accept";
    private final String suffix_complete = "complete";

    private int maxCode(String itemId) {
        LambdaQueryWrapper<WorkOrder> lq = Wrappers.lambdaQuery();
        lq.eq(WorkOrder::getCreateOrderItemId, itemId);

        Optional<WorkOrder> obj = workOrderMapper.selectList(lq).stream().max(Comparator.comparingInt(WorkOrder::getCode));
        if (obj.isPresent()) {
            return obj.get().getCode() + 1;
        } else {
            return 1;
        }
    }

    @Transactional
    @Override
    public String add(WorkOrderAddDto req, List<MultipartFile> files) {

        checkRole(req.getCreateRoleType(), req.getCreatetRoleId());
        WorkOrder obj = addReady(maxCode(req.getCreateOrderItemId()), false, req);
        obj.insert();

        OrderItemExt orderItem = orderService.queryItemById(obj.getCreateOrderItemId());
        if (orderItem == null) {
            throw new BusinessException("无效的订单项目。");
        }
        if (orderItem.getPriceConfirmType() == ProductPriceConfirmTypeEnum.AcceptConfirm) {
            orderService.updateQtyAndPrice(new OrderItemUpdateQtyAndPriceDto(obj.getCreateOrderItemId(), req.getItemQty(), req.getItemPrice()));
        }

        if (files != null) {
            if (files.size() > 0) {
                List<String> keys = OSSUtil.batchUpload(files, String.format("%s/%s/%s/", prefix, obj.getId(), suffix_create));
                if (keys.size() > 0) {
                    obj.setCreateAttach(String.join(",", keys));
                    obj.updateById();
                }
            }
        }
        return obj.getId();
    }

    @Override
    public WorkOrder addReady(int code, boolean isAutoComplete, WorkOrderAddDto req) {
        checkRole(req.getCreateRoleType(), req.getCreatetRoleId());
        WorkOrder obj = new WorkOrder();

        if (SecurityUtils.getUserContent().getType() == UserTypeEnum.OTHER) {
            obj.setCreateRoleType(RoleTypeEnum.Customer);
        } else {
            obj.setCreateRoleType(RoleTypeEnum.User);
        }
        obj.setCreateRoleId(req.getCreatetRoleId());
        obj.setCreateRemark(req.getCreateRemark());
        obj.setCreateOrderItemId(req.getCreateOrderItemId());
        obj.setPlanCompleteTime(req.getPlanCompleteTime());
        obj.setIsDelete(false);
        obj.setCreateRemark(req.getCreateRemark());
        if (req.getCreateRoleType() == RoleTypeEnum.User && SecurityUtils.getUserContent().getId().equals(req.getCreatetRoleId())) {
            obj.setCreateStatus(true);
        }

        if (isAutoComplete) {
            obj.setAcceptStatus(true);
            obj.setAcceptUserId(SecurityUtils.getUserContent().getId());
            obj.setAcceptUserName(SecurityUtils.getUserContent().getPersonnelName());
            obj.setAcceptRemark("虚拟项目，自动受理。");
            obj.setAcceptTime(new Date());
            obj.setCompleteStatus(true);
            obj.setCompleteUserId(obj.getAcceptUserId());
            obj.setCompleteUserName(obj.getAcceptUserName());
            obj.setCompleteTime(obj.getAcceptTime());
            obj.setCompleteRemark("虚拟项目，自动完成。");
            obj.setCompleteAuditDesc("无需审核。");
            obj.setCompleteAuditTime(obj.getCompleteTime());
            obj.setCompleteAuditUserId(obj.getAcceptUserId());
            obj.setCompleteAuditUserName(obj.getAcceptUserName());
        }
        return obj;
    }

    @Override
    public List<WorkOrder> addReady(int code, int qty, boolean isAutoComplete, WorkOrderAddDto req) {
        List<WorkOrder> result = new ArrayList<>();
        for (int i = 0; i < qty; i++) {
            result.add(addReady(code, isAutoComplete, req));
            code = code + 1;
        }
        return result;
    }

    @Override
    public void update(WorkOrderUpdateDto req, List<MultipartFile> files) {
        WorkOrder obj = getById(req.getId());
        if (!SecurityUtils.getUserContent().getId().equals(obj.getCreateAt())) {
            throw new BusinessException("只有创建人才能修改。");
        }
        if (obj.getCreateStatus()) {
            throw new BusinessException("工单已提交，不能修改。");
        }
        if (files != null) {
            if (files.size() > 0) {
                List<String> keys = OSSUtil.batchUpload(files, String.format("%s/%s/%s/", prefix, obj.getId(), suffix_create));
                obj.setCreateAttach(obj.getAcceptAttach() + "," + String.join(",", keys));
            }
        }
        obj.setCreateRemark(req.getCreateRemark());
        obj.updateById();
    }

    @Transactional
    @Override
    public void updatePlanCompleteTime(List<WorkOrderChangePlanCompleteTimeDto> req) {
        for (WorkOrderChangePlanCompleteTimeDto r : req) {
            WorkOrder wo = new WorkOrder();
            wo.setId(r.getId());
            wo.setPlanCompleteTime(r.getPlanCompleteTime());
            wo.setCreateRemark(r.getRemark());
            wo.updateById();

            wo = getById(r.getId());

            OrderItem item = new OrderItem();
            item.setId(wo.getCreateOrderItemId());
            item.setStartTime(r.getPlanCompleteTime());
            item.updateById();
        }
    }

    @Override
    public void updatePlanCompleteTime(String id, Date planCompleteTime, String remark) {
        WorkOrderChangePlanCompleteTimeDto obj = new WorkOrderChangePlanCompleteTimeDto();
        obj.setId(id);
        obj.setPlanCompleteTime(planCompleteTime);
        obj.setRemark(remark);
        updatePlanCompleteTime(Arrays.asList(obj));
    }

    @Override
    public int changePersonnel(String personnelId, String toPersonnelId) {
        Personnel personnel = personnelService.queryById(personnelId);
        if (personnel == null) {
            return 0;
        }

        Personnel toPersonnel = personnelService.queryById(toPersonnelId);
        if (toPersonnel == null) {
            return 0;
        }

        LambdaQueryWrapper<WorkOrder> lq = Wrappers.lambdaQuery();
        lq.eq(WorkOrder::getAcceptUserId, personnel.getUserId());
        lq.eq(WorkOrder::getAcceptStatus, true);
        lq.eq(WorkOrder::getCompleteStatus, false);
        List<WorkOrder> list = baseMapper.selectList(lq);
        for (WorkOrder obj : list) {
            obj.setAcceptUserId(toPersonnel.getUserId());
            obj.updateById();
        }
        return list.size();
    }

    @Override
    public void notify(String userId, WorkOrderExt data) {
//        String templateId = configureService.getValueByCode(WorkOrderConfigureCode.work_order_notify_id);
//        //String config = configureService.getValueByCode(WorkOrderConfigureCode.work_order_notify_config);
//        String url = StringUtils.valueReplace(configureService.getValueByCode(WorkOrderConfigureCode.work_order_notify_url), "\\{", "\\}", SecurityUtils.getUserContent());
//
//
//        wxService.sendTemplateMessage(
//                data.getTenantId(),
//                "新工单通知",
//                userId,
//                templateId,
//                StringUtils.splitTemplate(config.split("~"), data),
//                url);
//
//        wxService.sendTemplateMessage(
//                data.getTenantId(),
//                "新工单通知",
//                "9bddd1d360947dbd79a39499148a7645",
//                templateId,
//                StringUtils.splitTemplate(config.split("~"), data),
//                url);
    }

    @Override
    public List<WorkOrder> queryByItemId(String id) {
        LambdaQueryWrapper<WorkOrder> lq = Wrappers.lambdaQuery();
        lq.eq(WorkOrder::getCreateOrderItemId, id);
        return baseMapper.selectList(lq);
    }

    @Override
    public List<WorkOrderExt> queryViewByItemId(String id) {
        LambdaQueryWrapper<WorkOrderExt> lq = Wrappers.lambdaQuery();
        lq.eq(WorkOrderExt::getCreateOrderItemId, id);
        return workOrderExtMapper.selectList(lq);
    }

    @Override
    public List<WorkOrderExt> queryViewByOrder(String orderId) {
        LambdaQueryWrapper<WorkOrderExt> lq = Wrappers.lambdaQuery();
        lq.eq(WorkOrderExt::getOrderId, orderId);
        return workOrderExtMapper.selectList(lq);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public List<String> assign(WorkOrderAssignDto req) {
        List<String> result = new ArrayList<>();
        OrderItemExt item = orderService.queryItemById(req.getItemId());
        if (item == null) {
            throw new BusinessException("无效的订单项目。");
        }
        if (item.getDeliverStatus()) {
            throw new BusinessException("此订单项已完成交付，不能再次分配交付任务。");
        }
//        if (item.getStartTime() == null) {
//            throw new BusinessException("此订单未指定计划交付时间，请确认计划交付时间后才能执行此操作。");
//        }
//        if (item.getStartTime().before(new Date())) {
//            throw new BusinessException("计划交付时间不能是已经过去的时间。");
//        }
        if (item.getUnitType() == ProductUnitTypeEnum.ProductQty || item.getUnitType() == ProductUnitTypeEnum.ResourceTimeLen) {
            if (req.getUserIds().size() > 1) {
                throw new BusinessException("+【" + item.getUnitType().getDesc() + "】类商品的工单不能分配给多人。");
            }
        }

        for (String userId : req.getUserIds()) {
            if (StringUtils.isNullOrEmpty(userId)) {
                throw new BusinessException("分配的人员用户ID不能为空。");
            }

            WorkOrder wo = baseMapper.selectById(req.getId());

            if (wo == null) {
                wo = new WorkOrder();
                wo.setCode(maxCode(req.getItemId()));
            } else {
                if (wo.getPlanCompleteTime() == null) {
                    if (item.getStartTime() == null) {
                        throw new BusinessException("此工单没有指定计划完成时间。");
                    } else {
                        wo.setPlanCompleteTime(item.getStartTime());
                    }
                }
                if (!StringUtils.isNullOrEmpty(wo.getAcceptUserId())) {
                    if (userId.equals(wo.getAcceptUserId())) {
                        throw new BusinessException("不能重复分配给同一个用户。");
                    }
                }
            }
            Personnel p = personnelService.queryByUserId(userId);
            if (p == null) {
                throw new BusinessException("指定的分配人没有找到。");
            }
            wo.setCreateRoleType(RoleTypeEnum.User);
            wo.setCreateRoleId(SecurityUtils.getUserContent().getId());
            wo.setCreateOrderItemId(req.getItemId());
            wo.setCreateStatus(true);
            wo.setAcceptUserId(userId);
            wo.setAcceptUserName(p.getName());
            wo.setAcceptStatus(false);
            wo.insertOrUpdate();
            result.add(wo.getId());

            assignNotify(wo.getId());
        }
        return result;
    }

    private void assignNotify(String id) {
        String templateId = configureService.getValueByCode(WorkOrderConfigureCode.work_order_assign_templete_id);
        String config = configureService.getValueByCode(WorkOrderConfigureCode.work_order_assign_templete_config);
        String url = StringUtils.valueReplace(configureService.getValueByCode(WorkOrderConfigureCode.work_order_assign_templete_url), "\\{", "\\}", SecurityUtils.getUserContent());

        WorkOrderExt wo = queryViewById(id);
        wxService.sendTemplateMessage(
                wo.getTenantId(),
                "新工单通知",
                wo.getAcceptUserId(),
                templateId,
                StringUtils.splitTemplate(config.split("~"), wo),
                url);
    }

    @Override
    public void assignCancel(String id) {
        WorkOrder wo = baseMapper.selectById(id);
        if (wo == null) {
            throw new BusinessEntityNotFoundException(id, "工单");
        }
        if (wo.getAcceptStatus()) {
            if (!SecurityUtils.getUserContent().getId().equals(wo.getAcceptUserId())) {
                throw new BusinessException("工单已在进行中，只有工单执行人才可以撤销。");
            }
        }

        LambdaQueryWrapper<WorkOrder> lq = Wrappers.lambdaQuery();
        lq.eq(WorkOrder::getCreateOrderItemId, wo.getCreateOrderItemId());
        lq.eq(WorkOrder::getCompleteStatus, false);
        lq.ne(WorkOrder::getId, id);
        Integer cnt = baseMapper.selectCount(lq);

        if (cnt > 0) {
            wo.deleteById();
        } else {
            wo.setAcceptUserId(null);
            wo.setAcceptUserName(null);
            wo.updateById();
        }

    }

    @Transactional
    @Override
    public boolean startFollowUpItem(String orderId, String itemId) {
        boolean hasNextFollow = false;
        List<OrderItemExt> items = orderService.queryItemViewByOrderId(orderId);
        Optional<OrderItemExt> parent = items.stream().filter(s -> s.getId().equals(itemId)).findFirst();
        if (parent.isPresent()) {
            List<OrderItemExt> childs = items.stream().filter(s -> parent.get().getSkuId().equals(s.getSkuItemSkuId())).collect(Collectors.toList());
            if (StringUtils.isNullOrEmpty(childs)) {
                if (!StringUtils.isNullOrEmpty(parent.get().getSkuItemSkuId())) {
                    childs = items.stream().filter(s -> parent.get().getSkuItemId().equals(s.getSkuItemParentId())).collect(Collectors.toList());
                }
            }
            for (OrderItemExt item : childs) {
                if (!StringUtils.isNullOrEmpty(parent.get().getSkuItemId())) {
                    if (!parent.get().getSkuItemId().equals(item.getSkuItemParentId())) {
                        continue;
                    }
                }

                if (StringUtils.isNullOrEmpty(parent.get().getSkuItemId()) && !StringUtils.isNullOrEmpty(item.getSkuItemParentId())) {
                    continue;
                }

                // 是否要走交付流程
                if (!item.getIsDeliverFlow()) {
                    continue;
                }

                // 如果已有工单，则不再继续创建
                if (queryCountByItem(item.getId()) <= 0) {
                    if (item.getUnitType() == ProductUnitTypeEnum.Service) {
                        addReady(1, item.getQty().intValue(), false, new WorkOrderAddDto(item.getId(), null, item.getStartTime())).stream().forEach(WorkOrder::insert);
                        hasNextFollow = true;
                    } else {
                        addReady(1, false, new WorkOrderAddDto(item.getId(), null, item.getStartTime())).insert();
                        hasNextFollow = true;
                    }
                }
            }
        }
        return hasNextFollow;
    }

    @Override
    public void submit(String id) {
        WorkOrder obj = getById(id);
        if (!SecurityUtils.getUserContent().getId().equals(obj.getCreateAt())) {
            throw new BusinessException("只有创建人才能修改。");
        }
        if (obj.getCreateStatus()) {
            throw new BusinessException("工单已提交，不能重复操作。");
        }
        obj.setCreateStatus(true);
        obj.updateById();
    }

    @Override
    public void accept(String id, String remark, List<MultipartFile> files) {
        WorkOrder obj = getById(id);
        if (!obj.getCreateStatus()) {
            throw new BusinessException("工单未提交，还不能受理。");
        }
        if (obj.getAcceptStatus()) {
            throw new BusinessException("工单已受理，不能重复操作。");
        }
        if (files != null) {
            if (files.size() > 0) {
                List<String> keys = OSSUtil.batchUpload(files, String.format("%s/%s/%s/", prefix, obj.getId(), suffix_accept));
                obj.setCreateAttach(obj.getAcceptAttach() + "," + String.join(",", keys));
            }
        }
        obj.setAcceptStatus(true);
        obj.setAcceptUserId(SecurityUtils.getUserContent().getId());
        obj.setAcceptUserName(SecurityUtils.getUserContent().getPersonnelName());
        obj.setAcceptTime(new Date());
        obj.setAcceptRemark(remark);
        obj.updateById();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void complete(String id, String remark, Double qty, Double price, List<MultipartFile> files) {
        WorkOrder obj = getById(id);
        if (!SecurityUtils.getUserContent().getId().equals(obj.getAcceptUserId())) {
            throw new BusinessException("工单只能由受理人执行此操作。");
        }
        if (!obj.getAcceptStatus()) {
            throw new BusinessException("工单未受理，还不能提交完成。");
        }
        if (obj.getCompleteStatus()) {
            throw new BusinessException("工单已提交完成，不能重复操作。");
        }
        obj.setCompleteStatus(true);
        obj.setCompleteUserId(SecurityUtils.getUserContent().getId());
        obj.setCompleteUserName(SecurityUtils.getUserContent().getPersonnelName());
        obj.setCompleteTime(new Date());
        obj.setCompleteRemark(remark);

        obj.setCompleteAuditUserId(null);
        obj.setCompleteAuditUserName(null);
        obj.setCompleteAuditTime(null);
        obj.setCompleteAuditDesc(null);

        OrderItemExt orderItem = orderService.queryItemById(obj.getCreateOrderItemId());
        if (orderItem == null) {
            throw new BusinessException("无效的订单项目。");
        }

        String ids = configureService.getValueByCode(WorkOrderConfigureCode.tomb_bury_spu_ids);
        System.out.println("tomb_bury_spu_ids : " + ids);
        if (!StringUtils.isNullOrEmpty(ids)) {
            System.out.println("current spu id : " + orderItem.getSpuId());
            if (ids.contains(orderItem.getSpuId())) {
                System.out.println("buryComplete");
                // 下葬完成
                defunctService.buryComplete(orderItem.getDefunctId(), new Date());
            }
        }

        if (!orderItem.getIsDeliverAuditStatus()) {
            obj.setCompleteAuditUserId(SecurityUtils.getUserContent().getId());
            obj.setCompleteAuditTime(new Date());
            obj.setCompleteAuditDesc("自动完工确认");

            if (orderItem.getPriceConfirmType() == ProductPriceConfirmTypeEnum.AcceptConfirm) {
                orderService.deliverItem(obj.getCreateOrderItemId(), qty, price);
            } else {
                orderService.deliverItem(obj.getCreateOrderItemId());
            }
            startFollowUpItem(orderItem.getOrderId(), orderItem.getId());
        }

        if (files != null) {
            if (files.size() > 0) {
                List<String> keys = OSSUtil.batchUpload(files, String.format("%s/%s/%s/", prefix, obj.getId(), suffix_complete));
                if (keys.size() > 0) {
                    obj.setCompleteAttach(String.join(",", keys));
                }
            }
        }
        obj.updateById();

        WorkOrderExt view = queryViewById(obj.getId());
        String templateId = configureService.getValueByCode(WorkOrderConfigureCode.work_order_notify_id);
        String url = StringUtils.valueReplace(configureService.getValueByCode(WorkOrderConfigureCode.work_order_notify_url), "\\{", "\\}", SecurityUtils.getUserContent());
        wxService.sendTemplateMessage(
                obj.getTenantId(),
                obj.getCompleteUserId(),
                templateId,
                String.format("【%s，%s】已完工，请及时确认。", view.getName(), view.getSaleAttrDesc()),
                obj.getCompleteAuditUserName(),
                DateUtils.formatDate(new Date()),
                "",
                "",
                "请登录电脑端进行完工确认，如果已处理请忽略此信息。",
                url);
    }

    @Transactional
    @Override
    public void audit(String id, Boolean isPass, String desc) {
        if (isPass == null) {
            throw new BusinessException("isPass 参数不能为空。");
        }

        WorkOrderExt wo = queryById(id);
        if (wo == null) {
            throw new BusinessException("指定的工单没有找到。");
        }
        if (!wo.getCompleteStatus()) {
            throw new BusinessException("只有已完工的项目才能做完工确认。");
        }
        if (wo.getStatus() == WorkOrderStatusEnum.Close) {
            throw new BusinessException("已关闭的工单不能再次确认！");
        }
        WorkOrder obj = baseMapper.selectById(wo.getId());
        if (wo.getIsDeliverAuditStatus()) {
            obj.setCompleteStatus(isPass);
            obj.setCompleteAuditUserId(SecurityUtils.getUserContent().getId());
            obj.setCompleteAuditUserName(SecurityUtils.getUserContent().getPersonnelName());
            obj.setCompleteAuditTime(new Date());
            obj.setCompleteAuditDesc(desc);
            obj.updateById();

            // 如果通过，则开始自动创建后续工单
            if (isPass) {
                String ids = configureService.getValueByCode(WorkOrderConfigureCode.tomb_bury_spu_ids);
                if (!StringUtils.isNullOrEmpty(ids)) {
                    OrderItemExt orderItem = orderService.queryItemById(obj.getCreateOrderItemId());
                    if (ids.contains(orderItem.getSpuId())) {
                        System.out.println("buryComplete");
                        // 下葬完成
                        defunctService.buryComplete(orderItem.getDefunctId(), new Date());
                    }
                }

                if(!startFollowUpItem(wo.getOrderId(), wo.getCreateOrderItemId())){
                    Personnel personnel = personnelService.queryByUserId(wo.getCreateAt());
                    CustomerTraceEvent.publishEvent(this,
                            wo.getCustId(),
                            personnel == null ? null : personnel.getId(),
                            CustomerConfigureCode.service_return_visit,
                            String.format("%s，%s",wo.getName(),wo.getSaleAttrDesc()),
                            DateUtils.plusDay(1));
                }
            } else {
                String templateId = configureService.getValueByCode(WorkOrderConfigureCode.work_order_notify_id);
                String url = StringUtils.valueReplace(configureService.getValueByCode(WorkOrderConfigureCode.work_order_notify_url), "\\{", "\\}", SecurityUtils.getUserContent());
                wxService.sendTemplateMessage(
                        obj.getTenantId(),
                        obj.getCompleteUserId(),
                        templateId,
                        "工单被【" + obj.getCompleteAuditUserName() + "】退回，请及时处理。",
                        obj.getCompleteAuditUserName(),
                        DateUtils.formatDate(new Date()),
                        "",
                        "",
                        desc,
                        url);
            }
        }
    }

    @Override
    public void evaluate(String id, Integer score, String remark) {
        WorkOrder obj = getById(id);
        if (!SecurityUtils.getUserContent().getId().equals(obj.getCreateAt())) {
            throw new BusinessException("工单只能由创建人来进行评分。");
        }
        if (!obj.getCompleteStatus()) {
            throw new BusinessException("工单提交完成后才可以评价。");
        }
        if (obj.getEvaluateStatus()) {
            throw new BusinessException("工单已评价，不能重复操作。");
        }
        obj.setEvaluateStatus(true);
        obj.setEvaluateScore(score);
        obj.setEvaluateTime(new Date());
        obj.setEvaluateRemark(remark);
        obj.updateById();
    }

    @Override
    public WorkOrderExt queryById(String id) {
        return workOrderExtMapper.selectById(id);
    }

    private int queryCountByItem(String itemId) {
        LambdaQueryWrapper<WorkOrder> lq = Wrappers.lambdaQuery();
        lq.eq(WorkOrder::getCreateOrderItemId, itemId);
        return workOrderMapper.selectCount(lq);
    }

    @Override
    public List<WorkOrderExt> queryByIds(List<String> ids) {
        LambdaQueryWrapper<WorkOrderExt> lq = Wrappers.lambdaQuery();
        lq.in(WorkOrderExt::getId, ids);
        return workOrderExtMapper.selectList(lq);
    }

    @Override
    public List<GroupListInfo<WorkOrderExt>> queryStatusCount(String userId) {
        LambdaQueryWrapper<WorkOrderExt> lq = Wrappers.lambdaQuery();
        lq.eq(WorkOrderExt::getCreateAt, userId);
        lq.or().eq(WorkOrderExt::getAcceptUserId, userId);
        lq.or().eq(WorkOrderExt::getCompleteUserId, userId);
        IPage<WorkOrderExt> list = query(userId, null, 1, 9999);

        List<GroupListInfo<WorkOrderExt>> result = new ArrayList<>();

        GroupListInfo<WorkOrderExt> g2 = new GroupListInfo<>();
        g2.setName("待分配");
        g2.setId("2");
        g2.setCount((int) list.getRecords().stream().filter(s -> s.getCreateStatus() == true && s.getAcceptStatus() == false && StringUtils.isNullOrEmpty(s.getAcceptUserId())).count());
        g2.setItems(list.getRecords().stream().filter(s -> s.getCreateStatus() == true && s.getAcceptStatus() == false && StringUtils.isNullOrEmpty(s.getAcceptUserId())).collect(Collectors.toList()));
        result.add(g2);

        GroupListInfo<WorkOrderExt> g3 = new GroupListInfo<>();
        g3.setName("待受理");
        g3.setId("3");
        g3.setCount((int) list.getRecords().stream().filter(s -> userId.equals(s.getAcceptUserId()) && s.getAcceptStatus() == false && s.getCreateStatus() == true && s.getCompleteStatus() == false).count());
        g3.setItems(list.getRecords().stream().filter(s -> userId.equals(s.getAcceptUserId()) && s.getAcceptStatus() == false && s.getCreateStatus() == true && s.getCompleteStatus() == false).collect(Collectors.toList()));
        result.add(g3);

        GroupListInfo<WorkOrderExt> g4 = new GroupListInfo<>();
        g4.setName("待完成");
        g4.setId("4");
        g4.setCount((int) list.getRecords().stream().filter(s -> userId.equals(s.getAcceptUserId()) && s.getAcceptStatus() == true && s.getCompleteStatus() == false).count());
        g4.setItems(list.getRecords().stream().filter(s -> userId.equals(s.getAcceptUserId()) && s.getAcceptStatus() == true && s.getCompleteStatus() == false).collect(Collectors.toList()));
        result.add(g4);

        GroupListInfo<WorkOrderExt> g5 = new GroupListInfo<>();
        g5.setName("已完成");
        g5.setId("5");
        g5.setCount((int) list.getRecords().stream().filter(s -> userId.equals(s.getAcceptUserId()) && s.getCompleteStatus() == true).count());
        g5.setItems(list.getRecords().stream().filter(s -> userId.equals(s.getAcceptUserId()) && s.getCompleteStatus() == true).collect(Collectors.toList()));
        result.add(g5);

        GroupListInfo<WorkOrderExt> g1 = new GroupListInfo<>();
        g1.setName("全部");
        g1.setId("6");
        g1.setCount(list.getRecords().size());
        g1.setItems(list.getRecords());
        result.add(g1);

        return result;
    }

    @Override
    public IPage<WorkOrderExt> query(String userId, WorkOrderStatusEnum status, int pageIndex, int pageSize) {
        Page<WorkOrderExt> page = new Page(pageIndex, pageSize);
        LambdaQueryWrapper<WorkOrderExt> lq = Wrappers.lambdaQuery();
        lq.eq(WorkOrderExt::getIsVirtual, false);
        if (!StringUtils.isNullOrEmpty(userId)) {
            lq.eq(WorkOrderExt::getCreateAt, userId);
            lq.or().eq(WorkOrderExt::getAcceptUserId, userId);
            lq.or().eq(WorkOrderExt::getCompleteUserId, userId);

            List<String> ids = customerService.queryCurrentCustomerAndDefunct().stream().map(s -> s.getCustomerId()).distinct().collect(Collectors.toList());
            if (!StringUtils.isNullOrEmpty(ids)) {
                lq.in(WorkOrderExt::getCustId, ids);
            }
        }
        if (status == null) {
            return workOrderExtMapper.selectPage(page, lq);
        }
        switch (status) {
            case NotAssign:
                lq.isNull(WorkOrderExt::getAcceptUserId);
                lq.eq(WorkOrderExt::getCreateStatus, true);
                lq.eq(WorkOrderExt::getAcceptStatus, false);
                //lq.orderByDesc(WorkOrderExt::getCreateTime);
                break;
            case NotAccept:
                lq.eq(WorkOrderExt::getCreateStatus, true);
                lq.eq(WorkOrderExt::getAcceptStatus, false);
                lq.eq(WorkOrderExt::getCompleteStatus, false);
                lq.isNotNull(WorkOrderExt::getAcceptUserId);
                //lq.orderByDesc(WorkOrderExt::getCreateTime);
                break;
            case NotComplete:
                lq.eq(WorkOrderExt::getAcceptStatus, true);
                lq.eq(WorkOrderExt::getCompleteStatus, false);
                //lq.orderByDesc(WorkOrderExt::getAcceptTime);
                break;
            case NotEvaluate:
                lq.eq(WorkOrderExt::getCompleteStatus, true);
                lq.eq(WorkOrderExt::getEvaluateStatus, false);
                lq.gt(WorkOrderExt::getCompleteTime, DateUtils.parseDate(new Date(), "yyyy-MM-dd"));
                break;
            default:
                break;
        }
        //lq.ne(WorkOrderExt::getStatus, WorkOrderStatusEnum.Close);
        lq.orderByAsc(WorkOrderExt::getSortTime);
        return workOrderExtMapper.selectPage(page, lq);
    }

    @Override
    public IPage<WorkOrderExt> queryByCustomer(String customerId, WorkOrderStatusEnum status, int pageSize, int pageIndex) {
        Page<WorkOrderExt> page = new Page<>(pageIndex,pageSize);
        LambdaQueryWrapper<WorkOrderExt> lq = Wrappers.lambdaQuery();
        lq.eq(WorkOrderExt::getCustId,customerId);
        switch (status){
            case NotAssign:
                lq.eq(WorkOrderExt::getCreateStatus,false);
                lq.isNull(WorkOrderExt::getAcceptUserId);
                lq.orderByDesc(WorkOrderExt::getCreateTime);
                break;
            case NotAccept:
                lq.eq(WorkOrderExt::getCreateStatus,true);
                lq.isNull(WorkOrderExt::getAcceptUserId);
                lq.eq(WorkOrderExt::getAcceptStatus,false);
                lq.orderByDesc(WorkOrderExt::getCreateTime);
                break;
            case NotComplete:
                lq.eq(WorkOrderExt::getAcceptStatus,true);
                lq.eq(WorkOrderExt::getCompleteStatus,false);
                lq.orderByDesc(WorkOrderExt::getAcceptTime);
                break;
            case Close:
                lq.eq(WorkOrderExt::getCompleteStatus,true);
                lq.isNotNull(WorkOrderExt::getCompleteAuditUserId);
                lq.orderByDesc(WorkOrderExt::getCompleteTime);
                break;
            default:
                break;
        }
        return workOrderExtMapper.selectPage(page,lq);
    }

    @Override
    public WorkOrderVo queryViewById(String id) {
        WorkOrderExt workOrder = workOrderExtMapper.selectById(id);
        if (workOrder == null) {
            throw new BusinessEntityNotFoundException(id, "工单");
        }

        if (!StringUtils.isNullOrEmpty(workOrder.getCreateAttach())) {
            List<String> objs = new ArrayList<>();
            for (String url : workOrder.getCreateAttach().split(",")) {
                if (StringUtils.isNullOrEmpty(url)) {
                    continue;
                }
                objs.add(OSSUtil.getObjectUrl(url).toString());
            }
            workOrder.setCreateAttach(objs.toString());
        }

        if (!StringUtils.isNullOrEmpty(workOrder.getAcceptAttach())) {
            List<String> objs2 = new ArrayList<>();
            for (String url : workOrder.getAcceptAttach().split(",")) {
                if (StringUtils.isNullOrEmpty(url)) {
                    continue;
                }
                objs2.add(OSSUtil.getObjectUrl(url).toString());
            }
            workOrder.setAcceptAttach(objs2.toString());
        }

        if (!StringUtils.isNullOrEmpty(workOrder.getCompleteAttach())) {
            List<String> objs3 = new ArrayList<>();
            for (String url : workOrder.getCompleteAttach().split(",")) {
                if (StringUtils.isNullOrEmpty(url)) {
                    continue;
                }
                objs3.add(OSSUtil.getObjectUrl(url).toString());
            }
            workOrder.setCompleteAttach(objs3.toString());
        }

        WorkOrderVo result = new WorkOrderVo();
        BeanUtils.copyProperties(workOrder, result);
        //result.setForm(getSkuFormObject(workOrder.getCreateOrderItemId()));

        //加载订单项的附件
        List<OrderAttr> orderAttrs = orderService.queryAttrByItem(workOrder.getCreateOrderItemId());
        List<String> objs4 = new ArrayList<>();
        for (OrderAttr attr : orderAttrs) {
            objs4.add(OSSUtil.getObjectUrl(attr.getFileUrl()).toString());
        }
        result.setOrderItemImages(objs4);

        return result;
    }

    private void checkRole(RoleTypeEnum type, String id) {
        switch (type) {
            case User:
                User user = userMapper.selectById(id);
                if (user == null) {
                    throw new BusinessEntityNotFoundException("id", "创建者角色【用户】");
                }
                break;
            case Customer:
                Customer customer = customerMapper.selectById(id);
                if (customer == null) {
                    throw new BusinessEntityNotFoundException(id, "创建者角色【客户】");
                }
                break;
        }
    }

}